
from xml.dom import minidom
import sys
import gzip
import shutil
import os

class PixieC:
	def __init__(self):
		self.open = True
	def blockToStage(self, block):
		if (block.module == "Blink"):
			return "BlinkStage(PIXIE_PRIORITY_NORM, 1)"
		if (block.module == "Timer"):
			str = "TimerStage(" + block.parameters["Interval"].value + ")"
			return str
		if (block.module == "LEDs"):
			return "LEDStage(PIXIE_PRIORITY_NORM)"
		if (block.module == "Count"):
			return "CountStage(PIXIE_PRIORITY_NORM)"
		if (block.module == "SendMessage"):
			return "OpalSendStage(PIXIE_PRIORITY_NORM)"
		if (block.module == "RecieveMessage"):
			return "OpalReceiveStage(PIXIE_PRIORITY_NORM)"
	def writeNesCFile(self,links, blocks):
		header =  '#include "Pixie.h"\n'
		header += '#include "message.h"\n'
		header += '#include "Opal.h"\n'
		header += "configuration " + "OpalC" + "\n"
		header += "{ \n"
		header += "} \n \n"
		
		implementation = "implementation\n" + "{\n"
		implementation += self.writeComponentDefs(blocks)
		implementation += self.writeWiring(links)
		implementation += "\n}\n"

		doc = header + implementation
		return doc
	def writeComponentDefs(self, blocks):
		components = self.writeDefaultComponents()
		for b in blocks:
			component = blocks[b]
			line = "\tcomponents new " + self.blockToStage(component)
			line += " as " + component.module + component.id + ";\n"
			components.append(line)
		out = ""
		for comp_def in components:
			out += comp_def
		out += "\n"
		return out
	def writeDefaultComponents(self):
		str = [] 
		str.append("\tcomponents new SendStage(PIXIE_PRIORITY_NORM, TOS_BCAST_ADDR, OpalMsg, AM_OPAL_MSG);\n")
		str.append("\tcomponents new ReceiveStage(OpalMsg, AM_OPAL_MSG);\n")
		return str
	def writeWiring(self, links):
		output = "\t"
		for link in links:
			output += link.src.parent.module + link.src.parent.id + ".Output"
			output += " -> "
			output += link.dest.parent.module + link.dest.parent.id + ".Input"
			output += ";"
			output += "\n\t"
			if link.dest.parent.module == "SendMessage":
				output += link.dest.parent.module + link.dest.parent.id +".Output -> SendStage.Input;\n\t"
			if link.src.parent.module == "RecieveMessage":
				output += "ReceiveStage.Output -> " + link.src.parent.module + link.src.parent.id + ".Input;\n\t"
		return output

class parameter:
	def __init__(self, name, value):
		self.name = name
		try:
			self.value = value.firstChild.toxml()
		except:
			self.value = ""
class connection:
	def __init__(self, src, dest):
		self.src = src
		self.dest = dest
	def toString(self):
		out = self.src.parent.module + "." + self.src.name
		out += "--------->"
		out += self.dest.parent.module + "." + self.dest.name
		print out
class pin:
	def __init__(self, stage, pin_name, direction):
		self.parent = stage
		self.name = pin_name
		self.direction = direction
class block:
	def __init__(self, module, id, parameters):
		self.module = module
		self.id = id
		self.getParameters(parameters)
	def getParameters(self, parameters):
		self.parameters = dict()
		for p in parameters:
			name = p.getAttribute("name")
			value = p.getElementsByTagName('Value')
			if not value[0]:
				value[0] = ""
			self.parameters[name] = parameter(name, value[0])
	def toString(self):
		out = "Block \n"
		out += "\t Module Name: "+ str(self.module) + "\n"
		out += "\t ID: " + self.id + "\n"
		out += "\t Parameters:"
		for x in self.parameters:
			param = self.parameters[x]
			out += "\n"
			out += "\t =>" + "Name: " + param.name + ";"
			out += " " + "Value: " + param.value
		print out
		
class OpalParse():
	filename = sys.argv[1].rstrip(".eywx")
	doc = minidom.parse(sys.argv[1])
	blocks = dict()
	links = []
	readBlocks = doc.getElementsByTagName('Block')
	for b in readBlocks:
		name = b.getAttribute("class-id")
		id = b.getAttribute("id")
		parameters = b.getElementsByTagName("Parameter")
		blocks[id] = block(name,id,parameters)
	
	for link in doc.getElementsByTagName('Link'):
		pins = dict()
		for p in link.getElementsByTagName('Pin'):
			module = blocks[p.getAttribute('block')]
			name = p.getAttribute('id')
			if (p.getAttribute('type') == 'source'):
				direction = 'out'
			if (p.getAttribute('type') == 'target'):
				direction = 'in'
			pins[direction] = pin(module, name, direction)
		links.append(connection(pins['out'], pins['in']))					
			
	for n in blocks:
		blocks[n].toString()
		print "\n"
	print "Links:"
	for l in links:
		l.toString()
	doc = open('OpalC.nc', 'w')
	nesc = PixieC()
	config = nesc.writeNesCFile(links, blocks)
	doc.write(config)
	print config
	doc.close()
	src = os.path.abspath("./Template")
	dest = os.path.abspath("./"+name)
	opalc = os.path.abspath("OpalC.nc")
	print "Source = " + src +"\n"
	print "Destination = " + dest +"\n"
	print "OpalC file is at " + opalc + "\n"
	shutil.copytree(src, dest)
	shutil.copyfile(opalc, dest + "/OpalC.nc")
